package com.tzy.note.base.spring.custom.myautowired;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.stream.Stream;

public class MyAutowiredTest {
    /**
     * 把service对象，注入到 controller对象中
     *      0.controller类中定义service属性，并提供get、set方法
     *      1.首先要有controller、service对象
     *      2.获取controller的Class对象
     *      3.通过Class对象，获取controller的属性并拼成方法
     *      4.通过Class对象，获取方法名的对象
     *      5.方法名的对象把service对象，注入到controller对象属性中
     * @throws Exception
     */
    @Test
    public void testAutowired() throws Exception {
        //controller对象
        UserController userController = new UserController();
        //service对象
        UserService userService = new UserService();
        System.out.println(userService);

        //获取Class对象
        Class<? extends UserController> clazz = userController.getClass();
        //获取想要注入的属性的名称
        Field userServiceField = clazz.getDeclaredField("userService");
        userServiceField.setAccessible(true);//私有属性也可以获取到
        System.out.println(userServiceField);
        //获取属性的名称
        String fieldName = userServiceField.getName();
        System.out.println(fieldName);
        //获取set方法名称(拼接方法的名称,只有通过方法才能够设置具体的属性值)
        String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1,fieldName.length());
        System.out.println(methodName);
        //获取set方法对象(通过方法注入属性的对象)
        Method declaredMethod = clazz.getDeclaredMethod(methodName, UserService.class);
        System.out.println(declaredMethod);
        //执行set方法(反射)
        declaredMethod.invoke(userController,userService);
        System.out.println(userController.getUserService());
    }

    /**
     * 使用注解，比上面的，省去controller属性的set方法及service对象创建，
     * @throws Exception
     */
    @Test
    public void testMyAutowired() throws Exception {
        //controller对象
        UserController userController = new UserController();
        Class<? extends UserController> clazz = userController.getClass();
        //获取所有的属性值
        Stream.of(clazz.getDeclaredFields()).forEach(filed->{
            MyAutowired annotation = filed.getAnnotation(MyAutowired.class);
            if(annotation != null){
                filed.setAccessible(true);
                //获取属性的类型
                Class<?> type = filed.getType();
                try {
                    Object o = type.newInstance();
                    filed.set(userController,o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println(userController.getUserService());
    }
}
